package com.xtaller.test.base;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xtaller.test.anno.Table;
import com.xtaller.test.common.util.IdHelper;
import com.xtaller.test.common.util.JsonHelper;
import com.xtaller.test.common.util.TimeHelper;
import lombok.var;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.List;

/**
 * @version V1.0
 * @author: Taller
 * @date: 2019-09-05
 * @Description:
 */
public class BaseServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> {
    private final String PK_ID = "id";
    private final String CREATE_TIME = "createTime";

    /**
     * 创建数据
     * */
    public T model(T entity){
        JSONObject object = JsonHelper.o2j(entity);
        var id = 0L;
        var model = insertEntity(entity);
        if (object.get(PK_ID) == null || object.get(PK_ID).equals(0) || object.get(PK_ID).equals("")) {
            this.save(model);
            JSONObject tem = JsonHelper.o2j(model);
            id = tem.getLong("id");
        }else{
            var old = this.getById(object.getLong("id"));
            JSONObject oldObj = JsonHelper.o2j(old);
            if(oldObj.getLongValue("version") == object.getLongValue("version")){
                this.updateById(model);
                id = object.getLong("id");
            }else{
                id = 0;
            }
        }
        return this.getById(id);
    }

    private T insertEntity(T entity){
        JSONObject object = JsonHelper.o2j(entity);
        int vt = TimeHelper.getTimestamp();
        // 全局id
        var table = entity.getClass().getAnnotation(Table.class);

        if (object.get(PK_ID) == null || object.get(PK_ID).equals(0) || object.get(PK_ID).equals("")) {
            object.put(PK_ID, IdHelper.getLongId(table.id()));
            if(object.get(CREATE_TIME) == null || object.get(CREATE_TIME).equals(0) || object.get(CREATE_TIME).equals("")){
                object.put(CREATE_TIME, vt);
            }
        }else{
            object.put("updateTime", vt);
        }
        // 乐观锁判断
        if (this.checkLock(entity)) {
            object.put("version", vt);
        }
        return JSON.parseObject(JsonHelper.o2s(object), (Type) entity.getClass());

    }

    /**
     * 检查是否开启乐观锁
     * */
    private boolean checkLock(T t) {
        boolean check = false;
        Field[] fields = t.getClass().getDeclaredFields();

        for(int j = 0; j < fields.length; ++j) {
            String name = fields[j].getName().toLowerCase();
            if (name.equals("version")) {
                check = true;
                break;
            }
        }
        return check;
    }

    @Override
    public List<T> list(Wrapper<T> queryWrapper) {
        QueryWrapper<T> where = (QueryWrapper<T>) queryWrapper;
        where.eq("isDelete", 0);
        return super.list(queryWrapper);
    }

    @Override
    public List<T> list() {
        QueryWrapper<T> where = new QueryWrapper<>();
        where.eq("isDelete", 0);
        return list(where);
    }
}
